package MF1DSolver;

import java.util.ArrayList;

import jmeshless.NewOkCancelDialog;

import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import FEMShapeFunction1D.FEMShapeFunction1D1;
import Integration.GaussQuadrature;
import Integration.IFunction1D;
import Integration.derivavty;
import MeshlessShapeFunctions.JGaussian;
import MeshlessShapeFunctions.JMeshlessInterpolationFunction1DCoupled2;
import MeshlessShapeFunctions.JStKernel;
import MeshlessShapeFunctions.Particle;

public class enrichedFEM {
	protected double left;
	protected double right;
//	protected FEMShapeFunction1D1 lFEM;
//	protected FEMShapeFunction1D1 rFEM;
	protected ArrayList<Integer> femPos;
	protected ArrayList<FEMShapeFunction1D1> fem;
	protected ArrayList<JMeshlessInterpolationFunction1DCoupled2> mfList;
	protected IFunction1D p;
	protected IFunction1D q;
	protected IFunction1D w;
	protected IFunction1D f;
	
	public enrichedFEM(int numberOfMFParticles,ArrayList<FEMShapeFunction1D1> fem,ArrayList<Integer> femPos){
		this.fem = fem;
		this.femPos = femPos;
//		this.left = this.fem.get(0).getXi();
//		this.right = this.fem.get(fem.size()-1).getXi();
		this.left = 0.5;
		this.right = 1.0;
		double h = (right-left)/(double)numberOfMFParticles;
		
		ArrayList<Particle> ls1D = new ArrayList<Particle>();
        for (int i = 1; i <numberOfMFParticles; i++) {
            ls1D.add(new Particle(left+h*i, 0, i));
        }
        mfList = new ArrayList<JMeshlessInterpolationFunction1DCoupled2>();
        
        XYSeriesCollection col  = new XYSeriesCollection();
        
        for (int i = 0; i < ls1D.size(); i++) {
        	double rho = 2.7*h;
        	ls1D.get(i).setRho(rho);
            JMeshlessInterpolationFunction1DCoupled2 f = new JMeshlessInterpolationFunction1DCoupled2(1, ls1D.get(i).getX(), rho, new JGaussian(rho), fem);
            f.setNodeList(ls1D);
            mfList.add(f);
        }
        for (int i = 0; i < ls1D.size(); i++) {
        	JMeshlessInterpolationFunction1DCoupled2 f  = mfList.get(i);
            XYSeries series1 = new XYSeries("1", true, true);
            double x = 0.0;
            while(x<1.001){
            	double y = f.calculate(x);
            	series1.add(x,y);
                x+=0.01;
            }
            col.addSeries(series1);
        }
        
        NewOkCancelDialog dialog = new NewOkCancelDialog(null, false, col);
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
        this.left = 0.0;
		this.right = 1.0;
	}

	public double[][] generateMatrix(){
		double[][] res = new double[mfList.size()][mfList.size()];
		elementMatrixGeneratorMF1DEnriched gen = new elementMatrixGeneratorMF1DEnriched();
		gen.left = this.left;
		gen.right = this.right;
			for (int i = 0; i < mfList.size(); i++) {
				JMeshlessInterpolationFunction1DCoupled2 phi1  = mfList.get(i);
				gen.setPhi1(phi1);
				for (int j = 0; j < mfList.size(); j++) {
					JMeshlessInterpolationFunction1DCoupled2 phi2  = mfList.get(j);
					gen.setPhi2(phi2);
					gen.update();
					res[j][i] = gen.generateAll(p, q, w);
				}
			}
		
		return res;
	}
	
	public double[] generateFVector(){
		double[] res = new double[mfList.size()];
		elementMatrixGeneratorMF1DEnriched gen = new elementMatrixGeneratorMF1DEnriched();
		gen.left = this.left;
		gen.right = this.right;
			for (int i = 0; i < mfList.size(); i++) {
				JMeshlessInterpolationFunction1DCoupled2 phi1  = mfList.get(i);
				gen.setPhi1(phi1);
				res[i] = gen.generateFeElement(f);
			}
		
		return res;
	}
	
	public double[][] generateFEMMF(){
		double[][] res = new double[mfList.size()][fem.size()];
		GaussQuadrature gau = new GaussQuadrature(50);
		
		for (int i = 0; i < mfList.size(); i++) {
			final JMeshlessInterpolationFunction1DCoupled2 phi = mfList.get(i);
			for (int j = 0; j < fem.size(); j++) {
				final FEMShapeFunction1D1 lFEM = fem.get(j);
				res[i][j] = gau.justGauss(left, right, new IFunction1D() {
					
					@Override
					public double calculateDerivaty(double x) {
						// TODO Auto-generated method stub
						return 0;
					}
					
					@Override
					public double calculate(double x) {
						double p2 = phi.calculate(x);
	                	double p2p = phi.calculateDerivaty(x);
	                	double p1 = lFEM.calculate(x);
	                	double p1p = lFEM.calculateDerivaty(x);
	                	
	                    return p1*p2*q.calculate(x) + p1p*p2p*p.calculate(x) + p2*p1p*w.calculate(x);
					}
				});
			}
			
		}
		
		return res;
	}
	public double[][] generateMFFEM(){
		double[][] res = new double[fem.size()][mfList.size()];
		GaussQuadrature gau = new GaussQuadrature(50);
		
		for (int i = 0; i < mfList.size(); i++) {
			final JMeshlessInterpolationFunction1DCoupled2 phi = mfList.get(i);
			for (int j = 0; j < fem.size(); j++) {
				final FEMShapeFunction1D1 lFEM = fem.get(j);
				res[j][i] = gau.justGauss(left, right, new IFunction1D() {
					
					@Override
					public double calculateDerivaty(double x) {
						// TODO Auto-generated method stub
						return 0;
					}
					
					@Override
					public double calculate(double x) {
						double p1 = phi.calculate(x);
	                	double p1p = phi.calculateDerivaty(x);
	                	double p2 = lFEM.calculate(x);
	                	double p2p = lFEM.calculateDerivaty(x);
	                	
	                    return p1*p2*q.calculate(x) + p1p*p2p*p.calculate(x) + p2*p1p*w.calculate(x);
					}
				});
			}
			
		}
		
		return res;
	}
	
	public void setF(IFunction1D f) {
		this.f = f;
	}
	
	public void setP(IFunction1D p) {
		this.p = p;
	}
	
	public void setQ(IFunction1D q) {
		this.q = q;
	}
	
	public void setW(IFunction1D w) {
		this.w = w;
	}
	
	public ArrayList<Integer> getFEMPos() {
		return this.femPos;
	}
	
	public int getFEMPos(int i) {
		return this.femPos.get(i);
	}
}
